home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 52856 / 52856.xpi / chrome / content / handytab.js < prev    next >
Text File  |  2009-12-03  |  15KB  |  426 lines

  1. Components.utils.import("resource://handytab/datastore.jsm");
  2.  
  3. const FENNEC_APP_ID = "{a23983c0-fd0e-11dc-95ff-0800200c9a66}"
  4.  
  5. var handytab = {
  6.   mobileMode: false,
  7.   prefs: null,
  8.   homepage: "chrome://handytab/locale/handytab.html",
  9.   autosave: false,
  10.   markKey: 'x',
  11.   invertKey: 'z',
  12.   markKeyDown: false,
  13.   invertKeyDown: false,
  14.   markMode: false,
  15.   
  16.   prefListener : {
  17.     register: function() {
  18.       var branch = handytab.prefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
  19.       branch.addObserver("", this, false);
  20.     },
  21.     
  22.     observe: function(subject, topic, data) {
  23.       if (topic != "nsPref:changed") return;
  24.       switch (data) {
  25.         case "show.closebtn":
  26.           var tab = handytab.findTab(false, false);
  27.           if (tab) handytab.updateCloseButton(tab);
  28.           break;
  29.         case "homepage":
  30.           handytab.homepage = handytab.prefs.getCharPref("homepage");
  31.           break;
  32.         case "mark.key":
  33.           handytab.markKey = handytab.prefs.getCharPref("mark.key");
  34.           break;
  35.       }
  36.     }
  37.   },
  38.  
  39.   sendMarksToHtml: function(doc, all) {
  40.     var element = doc.getElementById("handytab-api");
  41.  
  42.     var marks = HandyTabDataStore.getMarks(all);
  43.     element.setAttribute("data", marks);
  44.  
  45.     var evt = doc.createEvent("Events");
  46.     evt.initEvent("HandyTabHtmlEvent", true, false);
  47.     element.dispatchEvent(evt);
  48.   },
  49.   
  50.   onHandyTabAddonEvent: function(e) {
  51.     if (e.target.ownerDocument.location != this.homepage) return;
  52.     
  53.     var subject = e.target.getAttribute("subject");
  54.     switch (subject) {
  55.       case "fetch-rows":
  56.         this.sendMarksToHtml(e.target.ownerDocument, true);
  57.         break;
  58.       case "remove-rows":
  59.         var args = e.target.getAttribute("args");
  60.         HandyTabDataStore.removeMarks(args);
  61.         break;
  62.     }
  63.   },
  64.  
  65.   log: function(msg) {
  66.     var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
  67.                                    .getService(Components.interfaces.nsIConsoleService);
  68.     consoleService.logStringMessage('handytab: ' + msg);
  69.   },
  70.   
  71.   catchLinkClick: function() {
  72.     var tab = this.mobileMode ? Browser.selectedTab.chromeTab : gBrowser.selectedTab;
  73.     if (tab.hasAttribute("handytab-hooked")) return;
  74.     tab.setAttribute("handytab-hooked", "true");
  75.     
  76.     var browser = this.mobileMode ? Browser.selectedBrowser : gBrowser.getBrowserForTab(tab);
  77.     
  78.     browser.addEventListener("keydown", function(e) {
  79.       var key = String.fromCharCode(e.which).toLowerCase();
  80.       if (handytab.markKey.toLowerCase() == key) {
  81.         handytab.markKeyDown = true;
  82.       }
  83.       else if (handytab.invertKey.toLowerCase() == key) {
  84.         handytab.invertKeyDown = true;
  85.       }
  86.     }, false);
  87.  
  88.     browser.addEventListener("keyup", function(e) {
  89.       var key = String.fromCharCode(e.which).toLowerCase();
  90.       if (handytab.markKey.toLowerCase() == key) {
  91.         handytab.markKeyDown = false;
  92.       }
  93.       else if (handytab.invertKey.toLowerCase() == key) {
  94.         handytab.invertKeyDown = false;
  95.       }
  96.     }, false);
  97.     
  98.     browser.addEventListener("click", function(e) {
  99.       if (e.button != 0 || e.ctrlKey || e.altKey || e.shiftKey) return;
  100.       if (e.target.tagName == "A" || e.target.tagName == "IMG" || e.target.parentNode.tagName == "A") {
  101.         if (((handytab.markMode && !handytab.invertKeyDown) || (!handytab.markMode && handytab.invertKeyDown)) &&
  102.             e.target.ownerDocument.location.toString() != handytab.homepage) {
  103.           handytab.addMark(e.target);
  104.           e.preventDefault();
  105.           e.stopPropagation();
  106.         }
  107.       } else if (handytab.markKeyDown) {
  108.         handytab.toogleMarkMode();
  109.       }
  110.     }, true);
  111.   },
  112.   
  113.   onLoad: function() {
  114.     this.initialized = true;
  115.     this.strings = document.getElementById("handytab-strings");
  116.  
  117.     var info = Components.classes["@mozilla.org/xre/app-info;1"]  
  118.                          .getService(Components.interfaces.nsIXULAppInfo);  
  119.     if (info.ID == FENNEC_APP_ID) this.mobileMode = true;
  120.     
  121.     var prefSrv = Components.classes["@mozilla.org/preferences-service;1"]
  122.                             .getService(Components.interfaces.nsIPrefService);
  123.     this.prefs = prefSrv.getBranch("extensions.handytab.options.");
  124.  
  125.     this.prefListener.register();
  126.  
  127.     HandyTabDataStore.init();
  128.  
  129.     this.autosave = this.prefs.getBoolPref("autosave");
  130.     if (this.autosave) HandyTabDataStore.load();
  131.     
  132.     this.markKey = this.prefs.getCharPref("mark.key");
  133.     this.invertKey = this.prefs.getCharPref("invert.key");
  134.     
  135.     this.catchLinkClick();
  136.     
  137.     document.addEventListener("HandyTabAddonEvent", function(e) { handytab.onHandyTabAddonEvent(e); }, false, true);
  138.  
  139.     if (this.mobileMode) {
  140.       var tabs = document.getElementById("tabs");
  141.       tabs.addEventListener("TabSelect", function(e) { handytab.onTabSelect(e); }, false);
  142.     } else {
  143.       var tabs = gBrowser.tabContainer;
  144.       tabs.addEventListener("SSTabRestored", function(e) { handytab.onSSTabRestored(e); }, false);
  145.       tabs.addEventListener("TabSelect", function(e) { handytab.onTabSelect(e); }, false);
  146.     }
  147.   },
  148.  
  149.   onUnload: function() {
  150.     if (!this.mobileMode) {
  151.       var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  152.                          .getService(Components.interfaces.nsIWindowMediator);
  153.       var enumerator = wm.getEnumerator("navigator:browser");
  154.       var count = 0;
  155.       while (count < 2 && enumerator.hasMoreElements()) {
  156.         var win = enumerator.getNext();
  157.         count++;
  158.       }
  159.       if (count == 2) return;
  160.     }
  161.     
  162.     var autosave = this.prefs.getBoolPref("autosave");
  163.  
  164.     if (autosave) HandyTabDataStore.save();
  165.     else if (this.autosave) HandyTabDataStore.reset();
  166.   },
  167.   
  168.   updateCloseButton: function(tab) {
  169.     var showbtn = this.prefs.getBoolPref("show.closebtn");
  170.     if (!showbtn) tab.setAttribute("hide-close-button", true);
  171.     else if (tab.hasAttribute("hide-close-button")) tab.removeAttribute("hide-close-button");
  172.   },
  173.   
  174.   makeHandyTab: function(tab) {
  175.     tab.setAttribute("handytab", "true");
  176.     tab.setAttribute("flex", 0);
  177.     tab.setAttribute("minwidth", 0);
  178.  
  179.     this.updateCloseButton(tab);
  180.     
  181.     var firsttab = this.prefs.getBoolPref("show.firsttab");
  182.     if (firsttab && gBrowser.tabContainer.itemCount != 1) gBrowser.moveTabTo(tab, 0);
  183.   },
  184.   
  185.   onSSTabRestored: function(e) {
  186.     var tab = e.originalTarget;
  187.     var ss = Components.classes["@mozilla.org/browser/sessionstore;1"]
  188.                        .getService(Components.interfaces.nsISessionStore);
  189.     var value = ss.getTabValue(tab, "handytab");
  190.     if (value) this.makeHandyTab(tab);
  191.   },
  192.   
  193.   onTabSelect: function(e) {
  194.     this.catchLinkClick();
  195.  
  196.     if (this.mobileMode) {
  197.       var tab = Browser.selectedTab;
  198.       if (!tab.chromeTab.hasAttribute("handytab")) return;
  199.       this.sendMarksToHtml(tab.browser.contentDocument, false);
  200.       return;
  201.     }
  202.     
  203.     var tab = gBrowser.selectedTab;
  204.     if (!tab.hasAttribute("handytab")) return;
  205.     
  206.     var browser = gBrowser.getBrowserForTab(tab);
  207.     this.sendMarksToHtml(browser.contentDocument, false);
  208.   },
  209.   
  210.   findTabInTabBrowser: function(tabbrowser) {
  211.     var numTabs = tabbrowser.browsers.length;
  212.  
  213.     for (var index = 0; index < numTabs; index++) {
  214.       var tab = tabbrowser.tabContainer.childNodes[index];
  215.       if (tab.hasAttribute("handytab")) return tab;
  216.     }
  217.  
  218.     return null;
  219.   },
  220.   
  221.   findTab: function(allwin, show) {
  222.     if (this.mobileMode) {
  223.       for (var i = 0; i < Browser._tabs.length; i++) {
  224.         var tab = Browser._tabs[i];
  225.         if (tab.chromeTab.hasAttribute("handytab")) {
  226.           if (show) Browser.selectedTab = tab;
  227.           return tab;
  228.         }
  229.       }
  230.       return null;
  231.     }
  232.     
  233.     if (!allwin) {
  234.       var tab = this.findTabInTabBrowser(gBrowser);
  235.       if (tab && show) gBrowser.selectedTab = tab;
  236.       return tab;
  237.     }
  238.     
  239.     var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  240.                        .getService(Components.interfaces.nsIWindowMediator);
  241.     var browserEnumerator = wm.getEnumerator("navigator:browser");
  242.  
  243.     while (browserEnumerator.hasMoreElements()) {
  244.       var browserWin = browserEnumerator.getNext();
  245.       var tabbrowser = browserWin.gBrowser;
  246.       
  247.       var tab = this.findTabInTabBrowser(tabbrowser);
  248.       if (tab) {
  249.         if (show) {
  250.           tabbrowser.selectedTab = tab;
  251.           browserWin.focus();
  252.         }
  253.         return tab;
  254.       }
  255.     }
  256.  
  257.     return null;
  258.   },
  259.   
  260.   showTab: function() {
  261.     var tab = this.findTab(true, true);
  262.     if (tab) return;
  263.     
  264.     if (this.mobileMode) {
  265.       var tab = Browser.addTab(this.homepage, true);
  266.       tab.chromeTab.setAttribute("handytab", "true");
  267.       return;
  268.     }
  269.     
  270.     tab = gBrowser.addTab(this.homepage);
  271.   
  272.     this.makeHandyTab(tab);
  273.     
  274.     var ss = Components.classes["@mozilla.org/browser/sessionstore;1"]
  275.                        .getService(Components.interfaces.nsISessionStore);
  276.     ss.setTabValue(tab, "handytab", true);
  277.     
  278.     gBrowser.selectedTab = tab;
  279.   },
  280.  
  281.   // Gather all descendent text under given document node.
  282.   gatherTextUnder: function(root) 
  283.   {
  284.     var text = "";
  285.     var node = root.firstChild;
  286.     var depth = 1;
  287.     while ( node && depth > 0 ) {
  288.       // See if this node is text.
  289.       if ( node.nodeType == Node.TEXT_NODE ) {
  290.         // Add this text to our collection.
  291.         text += " " + node.data;
  292.       } else if ( node instanceof HTMLImageElement) {
  293.         // If it has an alt= attribute, use that.
  294.         var altText = node.getAttribute( "alt" );
  295.         if ( altText && altText != "" ) {
  296.           text = altText;
  297.           break;
  298.         }
  299.       }
  300.       // Find next node to test.
  301.       // First, see if this node has children.
  302.       if ( node.hasChildNodes() ) {
  303.         // Go to first child.
  304.         node = node.firstChild;
  305.         depth++;
  306.       } else {
  307.         // No children, try next sibling.
  308.         if ( node.nextSibling ) {
  309.           node = node.nextSibling;
  310.         } else {
  311.           // Last resort is our next oldest uncle/aunt.
  312.           node = node.parentNode.nextSibling;
  313.           depth--;
  314.         }
  315.       }
  316.     }
  317.     // Strip leading whitespace.
  318.     text = text.replace( /^\s+/, "" );
  319.     // Strip trailing whitespace.
  320.     text = text.replace( /\s+$/, "" );
  321.     // Compress remaining whitespace.
  322.     text = text.replace( /\s+/g, " " );
  323.     return text;
  324.   },
  325.   
  326.   getLinkText: function(link) {
  327.     var text = this.gatherTextUnder(link);
  328.     if (!text.match(/\S/)) text = null;
  329.     if (!text) {
  330.       text = link.getAttribute("title");
  331.       if (!text.match(/\S/)) text = null;
  332.       if (!text) {
  333.         text = link.getAttribute("alt");
  334.         if (!text.match(/\S/)) text = null;
  335.       }
  336.     }
  337.     return text;
  338.   },
  339.   
  340.   markPage: function() {
  341.     var tab = this.mobileMode ? Browser.selectedTab.chromeTab : gBrowser.selectedTab;
  342.     var browser = this.mobileMode ? Browser.selectedBrowser : gBrowser.getBrowserForTab(tab);
  343.     this.addMark(browser.contentDocument.body);
  344.   },
  345.   
  346.   markLink: function(e) {
  347.     if (!gContextMenu || !gContextMenu.target) return;
  348.  
  349.     this.addMark(gContextMenu.target);
  350.   },
  351.   
  352.   addMark: function(target) {
  353.     var url;
  354.     var linktext;
  355.     
  356.     if (target.tagName == "A") {
  357.       url = target.href;
  358.       linktext = this.getLinkText(target);
  359.       if (!linktext) linktext = target.href;
  360.     } else if (target.tagName == "IMG") {
  361.       if (target.parentNode.tagName == "A") {
  362.         this.addMark(target.parentNode);
  363.         return;
  364.       }
  365.       url = target.src;
  366.       linktext = target.getAttribute("alt");
  367.       if (!linktext) linktext = url;
  368.     } else if (target.parentNode.tagName == "A") {
  369.       this.addMark(target.parentNode);
  370.       return;
  371.     } else {
  372.       url = target.ownerDocument.location.toString();
  373.       linktext = target.ownerDocument.title;
  374.     }
  375.  
  376.     var refer = target.ownerDocument.location.toString();
  377.     
  378.     var faviconService = Components.classes["@mozilla.org/browser/favicon-service;1"]
  379.                                    .getService(Components.interfaces.nsIFaviconService);
  380.     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  381.                               .getService(Components.interfaces.nsIIOService);
  382.  
  383.     var icon = "";
  384.     var uri = ioService.newURI(refer, null, null);
  385.     try {
  386.       var faviconURI = faviconService.getFaviconForPage(uri);
  387.       icon = faviconURI.spec;
  388.     } catch (err) {}
  389.  
  390.     var mark = {linktext: linktext, url: url, refer: refer, icon: icon, time: new Date()};
  391.     HandyTabDataStore.addMark(mark);
  392.     
  393.     var notify = this.prefs.getBoolPref("mark.notify");
  394.     
  395.     if (!notify) return;
  396.  
  397.     var alertsService = Components.classes["@mozilla.org/alerts-service;1"]
  398.                                   .getService(Components.interfaces.nsIAlertsService);
  399.     alertsService.showAlertNotification("chrome://handytab/skin/handytab.png",
  400.                                         this.strings.getString("extensions.handytab.msg.marked"),
  401.                                         url,
  402.                                         true);
  403.   },
  404.   
  405.   toogleMarkMode: function() {
  406.     this.markMode = !this.markMode;
  407.     if (this.mobileMode) {
  408.       var alertsService = Components.classes["@mozilla.org/alerts-service;1"]
  409.                                     .getService(Components.interfaces.nsIAlertsService);
  410.       var msg = this.markMode ? this.strings.getString("extensions.handytab.msg.markmode.on") :
  411.                                 this.strings.getString("extensions.handytab.msg.markmode.off");
  412.       alertsService.showAlertNotification("chrome://handytab/skin/handytab.png",
  413.                                           msg,
  414.                                           null,
  415.                                           true);
  416.     } else {
  417.       var statusicon = document.getElementById("handytab-status");
  418.       if (this.markMode) statusicon.setAttribute("markmode", true);
  419.       else statusicon.removeAttribute("markmode");
  420.     }
  421.   }
  422. };
  423.  
  424. window.addEventListener("load", function(e) { handytab.onLoad(e); }, false);
  425. window.addEventListener("unload", function(e) { handytab.onUnload(e); }, false);
  426.